#include "Node.h"
#include "Renderer.h"

namespace graphics
{

Node::Node()
{
	m_used = 0;
}
void Node::UpdateWorldData(float dt)
{
	//Update the node's own geometric state
	Spatial::UpdateWorldData(dt);

	//Update children's geometric states
	std::vector<Spatial*>::iterator Iter;
	Spatial* tempChild;
	for(Iter = m_child.begin(); Iter != m_child.end(); Iter++)
	{
		tempChild = *Iter;
		if(tempChild != NULL) tempChild->UpdateWorldData(dt);
	}
}
/*===================================================================================*/
/*NODE MODIFIERS*/
/*===================================================================================*/
int Node::AttachChild(Spatial* SpatialPtr)
{
	std::vector<Spatial*>::iterator Iter;
	bool childAttached = false;
	int childPosition=0;

	//Search the child vector to see if there are any empty spots
	for(Iter = m_child.begin(); Iter != m_child.end(); Iter++,childPosition++)
	{
		//If there is, attach the child here
		if(*Iter == NULL)
		{
			m_child.insert(Iter,SpatialPtr);
			//Increase occupied space count
			m_used++;
			childAttached = true;
			//Set the child's parent to this
			SpatialPtr->setParent(this);
			return childPosition;
		}
	}
	//If there are no empty spots in the vector
	if( !childAttached )
	{	
		//Attach the child to the end
		m_child.push_back(SpatialPtr);
		m_used++;
		//Set the child's parent to this
		SpatialPtr->setParent(this);
		//Return the last point on the vector
		return m_child.size()-1;
	}
}
int Node::DetachChild(Spatial* SpatialPtr)
{
	std::vector<Spatial*>::iterator Iter;
	int childPosition=0;

	//Seek in the child vector for...
	for(Iter = m_child.begin(); Iter != m_child.end(); Iter++,childPosition++)
	{
		//a child that points to same Spatial and release it.
		if(*Iter == SpatialPtr)
		{
			*Iter = NULL;
			//...Decrease occupied space count
			m_used--;
			//...Clear the parent
			SpatialPtr->setParent(NULL);
			return childPosition;
		}
	}
	//or return -1 for not found.
	return -1;

}
Spatial* Node::GetChild(int i)
{
	return m_child[i];
}
Spatial* Node::SetChild(int i, Spatial* SpatialPtr)
{
	Spatial* oldChild;

	//If index is within current vector limits...
	if(i<m_child.size())
	{
		//...Save the old child
		oldChild = m_child[i];
		//...Set the new child
		m_child[i] = SpatialPtr;
		//...Increase occupied space count if it was not occupied earlier
		if(oldChild == NULL) m_used++;
		//...Return the old child
		return oldChild;
	}
	//Otherwise return NULL for wrong index/empty index
	else return NULL;
}
Spatial* Node::DetachChildAt(int i)
{
	Spatial* detachedChild;
	//If index is within current vector limits...
	if(i<m_child.size())
	{
		//...Detach the child at index
		detachedChild = m_child[i];
		//...Set the index to NULL
		m_child[i] = NULL;
		//...Clear the parent
		m_child[i]->setParent(NULL);
		//...Decrease occupied space count
		m_used--;
		//...Return detached child (Still returns even if the index is NULL)
		return detachedChild;
	}
	//Otherwise return NULL for wrong index/empty index
	else return NULL;
}
int Node::getSize()
{
	return m_child.size();
}
int Node::getOccupied()
{
	return m_used;
}

/*===================================================================================*/
/*RENDER HANDLERS*/
/*===================================================================================*/
void Node::Draw(Renderer& RendererAddress)
{
	std::vector<Spatial*>::iterator Iter;
	for(Iter = m_child.begin(); Iter != m_child.end(); Iter++)
	{
		(*Iter)->SetRenderState(this->GetRenderStates());
		if(*Iter != NULL) (*Iter)->onDraw(RendererAddress);
	}
}

}/* namespace graphics */